/**************************************************************************
Step 1. Include necessary header files such that the stuff your test logic needs is declared. 
Don't forget gtest.h, which declares the testing framework.                                                   
**************************************************************************/
#include "gtest/gtest.h"
#include "include/pf_net.h"
#include "include/pf_file.h"
#include "include/pf_errno.h"
#include<errno.h>
#include <sys/socket.h>
#include<netinet/in.h>


/**************************************************************************
Step 2. Use test fixture to design your complex cases. 
You can add SetUp() to initialize the test data and 
TearDown() to clear the test data for common usage
Pls remember that when you using test fixture, need to use macro "TEST_F" instead of "TEST"                                                 
**************************************************************************/
class PfNetTest : public testing::Test 
{
    /* This SetUp() will be called before every TEST CASE which is marked by macro "TEST_F" */
    virtual void SetUp() 
    {
    }

    /* This TearDown will be called after every TEST CASE which is marked by macro "TEST_F" */
    virtual void TearDown() 
    {

    }
    public:

};
char listen_ip[16] = "127.0.0.1";
char connect_ip[16] = "127.0.0.1";

typedef struct Option
{
    int32_t timeout;
    int32_t counts;
    pf_fd_block_e block_type;
    uint16_t port;
    uint8_t send;
}Option_t;

void *client_func_write(void *arg)
{
    int ret;
    int sockfd;
    Option_t *opt         = (Option_t*)arg;
    pf_family_e family    = PF_INETV4;
    int32_t size          = 2*1024*1024;
    char *buf             = (char*)malloc(sizeof(char)*2*1024*1024);
    EXPECT_NE((char*)NULL, buf);
    memset(buf,1,size);
    while(opt->counts--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno  = 0;
        ret    = pf_connect(sockfd,connect_ip,opt->port,family,-1);
        if(opt->block_type == PF_FD_BLOCK)
        {
            ret=pf_set_nonblock(sockfd,PF_OFF)<<ret;
        }
        else if(opt->block_type == PF_FD_NONBLOCK)
        {
            ret=pf_set_nonblock(sockfd,PF_ON)<<ret;
        }
        else
        {
            //invalid paramter
        }
        if(opt->send == 1)
        {
            errno = 0;
            ret   = pf_write_n(sockfd,opt->block_type, buf, size, opt->timeout);
        }
        else if(opt->send == 0)
        {
            pf_wait_fd(-1,0,opt->timeout+1000); 
        }
        else
        {
            pthread_exit(NULL); 
        }
        close(sockfd);
    }
    free(opt);
    free(buf);
    return (void*)NULL;
}

void *client_func_writev(void *arg)
{
    int ret;
    int sockfd;
    Option_t *opt      = (Option_t*)arg;
    pf_family_e family = PF_INETV4;
    char *buf1 = (char*)malloc(sizeof(char)*1024*1024);
    char *buf2 = (char*)malloc(sizeof(char)*1024*1024);
    EXPECT_NE((char*)NULL, buf1);
    EXPECT_NE((char*)NULL, buf2);
    memset(buf1,1,1024*1024);
    memset(buf2,1,1024*1024);
    struct iovec iov[2];
    iov[0].iov_base = buf1;
    iov[0].iov_len  = 1024*1024;
    iov[1].iov_base = buf2;
    iov[1].iov_len  = 1024*1024;
    int iovcnt      = 2;

    while(opt->counts--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno  = 0;
        ret    = pf_connect(sockfd,connect_ip,opt->port,family,-1);
        if(opt->block_type == PF_FD_BLOCK)
        {
            pf_set_nonblock(sockfd,PF_OFF);
        }
        else if(opt->block_type == PF_FD_NONBLOCK)
        {
            pf_set_nonblock(sockfd,PF_ON);
        }
        else
        {
            //invalid paramter
        }
        if(opt->send)
        {
            ret = pf_writev_n(sockfd,opt->block_type, iov, iovcnt, opt->timeout);
        }
        else
        {
            pf_wait_fd(-1,0,opt->timeout+5000); 
        }
        close(sockfd);
    }
    free(opt);
    free(buf1);
    free(buf2);
    return (void*)NULL;
}

void *server_func_read(void* arg)
{
    Option_t *opt = (Option_t*)arg;
    int ret;
    int sockfd;
    pf_family_e family;
    uint16_t backlog;
    int connfd;
    struct sockaddr_in client_addr;
    typedef struct sockaddr SA;
    socklen_t len         = sizeof(struct sockaddr_in);
    int yes               = 1;
    int32_t size          = 2*1024*1024;
    char *buf             = (char*)malloc(sizeof(char)*2*1024*1024);
    EXPECT_NE((char*)NULL, buf);
    memset(buf,1,size);

    sockfd  = socket(AF_INET,SOCK_STREAM,0);
    family  = PF_INETV4;
    backlog = 5;
    errno   = 0;

    EXPECT_EQ(0, setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)));  
    ret     = pf_listen(sockfd,listen_ip,opt->port,family,backlog);
    EXPECT_EQ(0, ret)<<errno;
    while(opt->counts--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        if(opt->block_type == PF_FD_BLOCK)
        {
            pf_set_nonblock(connfd,PF_OFF);
        }
        else if(opt->block_type == PF_FD_NONBLOCK)
        {
            pf_set_nonblock(connfd,PF_ON);
        }
        else
        {
        }
        if(opt->send)
        {
            ret = pf_read_n(connfd, opt->block_type, buf, size, opt->timeout);
        }
        else
        {
            pf_wait_fd(-1,0,opt->timeout+1000); 
        }

        close(connfd);
    }
    free(opt);
    free(buf);
    close(sockfd);
    return (void*)NULL;
}

void *server_func_readv(void* arg)
{
    Option_t *opt   = (Option_t*)arg;
    int ret;
    int sockfd;
    pf_family_e family;
    uint16_t backlog;
    int connfd;
    struct sockaddr_in client_addr;
    typedef struct sockaddr SA;
    socklen_t len = sizeof(struct sockaddr_in);
    int yes;
    struct iovec iov[2];
    char *buf1 = (char*)malloc(sizeof(char)*1024*1024);
    char *buf2 = (char*)malloc(sizeof(char)*1024*1024);
    EXPECT_NE((char*)NULL, buf1);
    EXPECT_NE((char*)NULL, buf2);
    memset(buf1,1,1024*1024);
    memset(buf2,1,1024*1024);


    iov[0].iov_base = buf1;
    iov[0].iov_len  = 1024*1024;
    iov[1].iov_base = buf2;
    iov[1].iov_len  = 1024*1024;
    int iovcnt      = 2;

    sockfd  = socket(AF_INET,SOCK_STREAM,0);
    family  = PF_INETV4;
    backlog = 5;
    yes     = 1;
    EXPECT_EQ(0, setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)));  
    ret     = pf_listen(sockfd,listen_ip,opt->port,family,backlog);
    EXPECT_EQ(0, ret);
    while(opt->counts--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        if(opt->block_type == PF_FD_BLOCK)
        {
            pf_set_nonblock(connfd,PF_OFF);
        }
        else if(opt->block_type == PF_FD_NONBLOCK)
        {
            pf_set_nonblock(connfd,PF_ON);
        }
        else
        {
        }

        if(opt->send)
        {
            ret = pf_readv_n(connfd, opt->block_type, iov, iovcnt, opt->timeout);
        }
        else
        {
            pf_wait_fd(-1,0,opt->timeout+1000); 
        }
        close(connfd);
    }
    free(buf1);
    free(buf2);
    free(opt);
    close(sockfd);
    return (void*)NULL;
}

int start_thread(void *(*func)(void *), void *arg)
{
    pthread_t id;
    pthread_attr_t  attr;
    int             ret;
    Option_t *option = (Option_t*)malloc(sizeof(Option_t));
    EXPECT_NE((Option_t*)NULL, option);
    memcpy(option,arg,sizeof(Option_t));

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    if ((ret = pthread_create(&id, &attr,func,(void*)option)) != 0) 
    {
        return -1;
    }
    return 0;
}

/***************************************************************************
Step 3. Use macro "TEST_F" to start your test case                                      
You can design your test case as the example
***************************************************************************/

TEST_F(PfNetTest, pf_get_sockport_test)
{
    //TODO
    uint16_t ret;
    struct sockaddr_in addr_ipv4;
    struct sockaddr_in6 addr_ipv6;

    //test ipv4 normal
    addr_ipv4.sin_family      = AF_INET;
    addr_ipv4.sin_port        = htons(10021);
    addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
    ret                       = pf_get_sockport((pf_sockaddr_t*)&addr_ipv4);
    EXPECT_EQ(10021,ret);

    //test ipv6 normal
    addr_ipv6.sin6_family = AF_INET6;
    addr_ipv6.sin6_port   = htons(10022);
    ret                   = pf_get_sockport((pf_sockaddr_t*)&addr_ipv6);
    EXPECT_EQ(10022,ret);

    //test ipv6,family error
    errno                 = 0;
    addr_ipv6.sin6_family = 3555;
    addr_ipv6.sin6_port   = htons(10023);
    ret                   = pf_get_sockport((pf_sockaddr_t*)&addr_ipv6);
    EXPECT_EQ(0,ret);
    EXPECT_EQ(PF_INVALID,errno);

#ifndef VALGRIND_CHECK /* Death test core dump makes valgrind too many errors */
    //death test
    EXPECT_DEATH(pf_get_sockport(NULL),"");
#endif /* #ifndef VALGRIND_CHECK */

}

TEST_F(PfNetTest, pf_get_sockaddr_test)
{
    //TODO
    char* ret;
    char str[24];
    int32_t str_len;
    struct sockaddr_in addr_ipv4;

    //test ipv4 normal
    addr_ipv4.sin_family      = AF_INET;
    addr_ipv4.sin_port        = htons(10020);
    addr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
    str_len                   = 16;
    ret                       = pf_get_sockaddr((pf_sockaddr_t*)&addr_ipv4, str, str_len);
    EXPECT_NE((char*)NULL,ret);

    //length < INET_ADDRSTRLEN
    str_len = 0;
    ret     = pf_get_sockaddr((pf_sockaddr_t*)&addr_ipv4, str, str_len);
    EXPECT_EQ((char*)NULL,ret);

#ifndef VALGRIND_CHECK /* Death test core dump makes valgrind too many errors */
    //death test
    EXPECT_DEATH(pf_get_sockaddr(NULL,str,str_len),"");
    EXPECT_DEATH(pf_get_sockaddr((pf_sockaddr_t*)&addr_ipv4,NULL,str_len),"");
#endif /* #ifndef VALGRIND_CHECK */


}


TEST_F(PfNetTest, pf_listen_abnormal_test)
{
    int ret = -1;

    /* initilize test data for this case */
    int sockfd;
    pf_family_e family;
    uint16_t backlog;
    uint16_t port_lis = 10015;

    //sockfd is abnormal
    family  = PF_INETV4;
    backlog = 5;
    sockfd  = -1;
    ret     = pf_listen(sockfd,listen_ip,port_lis,family,backlog);
    EXPECT_NE(0, ret);

    //port is nagtive
    family  = PF_INETV4;
    backlog = 5;
    sockfd  = socket(AF_INET,SOCK_STREAM,0);
    EXPECT_LT(0, sockfd);
    errno = 0;
    ret   = pf_listen(sockfd,listen_ip,-1,family,backlog);
    EXPECT_EQ(0, ret)<<errno;
    close(sockfd);

    //port is 0
    family  = PF_INETV4;
    backlog = 5;
    sockfd  = socket(AF_INET,SOCK_STREAM,0);
    EXPECT_LT(0, sockfd);
    errno = 0;
    ret   = pf_listen(sockfd,listen_ip,0,family,backlog);
    EXPECT_EQ(0, ret)<<errno;
    close(sockfd);

    //backlog abnormal
    family  = PF_INETV4;
    backlog = 0;
    sockfd  = socket(AF_INET,SOCK_STREAM,0);
    EXPECT_LT(0, sockfd);
    errno = 0;
    ret   = pf_listen(sockfd,listen_ip,port_lis,family,backlog);
    EXPECT_EQ(0, ret)<<errno;
    close(sockfd);

    /*
     //family abnormal
    family  = -1;
    backlog = 5;
    sockfd  = socket(AF_INET,SOCK_STREAM,0);
    EXPECT_LT(0, sockfd);
    ret = pf_listen(sockfd,listen_ip,-1,family,backlog);
    EXPECT_NE(0, ret);
    close(sockfd);
    */

    //ip is abnormal
    family  = PF_INETV4;
    backlog = 5;
    sockfd  = socket(AF_INET,SOCK_STREAM,0);
    EXPECT_LT(0, sockfd);
#ifndef VALGRIND_CHECK /* Death test core dump makes valgrind too many errors */
    EXPECT_DEATH(pf_listen(sockfd,NULL,port_lis,family,backlog),"");
#endif /* #ifndef VALGRIND_CHECK */
    close(sockfd);
}

TEST_F(PfNetTest, pf_connect_abnormal_test)
{
    int ret;
    int sockfd;
    pf_family_e family = PF_INETV4;
    int32_t timeout    = 2*1000;
    uint16_t port_conn = 10010;

    /*sockfd is nagtive*/
    errno = 0;
    ret   = pf_connect(-1,connect_ip,port_conn,family,timeout);
    EXPECT_NE(0,ret)<<errno;

    /*port is nagtive*/
    errno  = 0;
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    ret    = pf_connect(sockfd,connect_ip,-1,family,timeout);
    EXPECT_NE(0,ret)<<errno;
    close(sockfd);

/*
    // family is not exsit
    errno  = 0;
    family = -1;
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    ret    = pf_connect(sockfd,connect_ip,port_conn,family,timeout);
    EXPECT_NE(0,ret)<<errno;
    close(sockfd);
    */

    /*domain is null*/
    family = PF_INETV4;
    sockfd = socket(AF_INET,SOCK_STREAM,0);
#ifndef VALGRIND_CHECK /* Death test core dump makes valgrind too many errors */
    EXPECT_DEATH(pf_connect(sockfd,NULL,port_conn,family,timeout),"");
#endif /* #ifndef VALGRIND_CHECK */
    close(sockfd);

    /*net is unconncetable*/
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    errno  = 0;
    ret    = pf_connect(sockfd,"192.168.0.2",port_conn,family,timeout);
    EXPECT_GT(0,ret)<<errno;
    close(sockfd);


    close(sockfd);

}

TEST_F(PfNetTest, pf_set_socket_option_net_test)
{

    int ret;
    int sockfd;
    int32_t size;
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    //pf_set_keepalive
    
    errno = 0;
    ret   = pf_set_keepalive(sockfd,PF_ON);
    EXPECT_EQ(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_keepalive(sockfd,PF_OFF);
    EXPECT_EQ(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_keepalive(sockfd,PF_INVALID);
    EXPECT_GT(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_keepalive(-1,PF_ON);
    EXPECT_GT(0,ret)<<errno;
    
    //pf_set_oobinline
    errno = 0;
    ret   = pf_set_oobinline(sockfd,PF_ON);
    EXPECT_EQ(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_oobinline(sockfd,PF_OFF);
    EXPECT_EQ(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_oobinline(sockfd,PF_INVALID);
    EXPECT_GT(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_oobinline(-1,PF_ON);
    EXPECT_GT(0,ret)<<errno;

    //pf_set_nodelay
    errno = 0;
    ret   = pf_set_nodelay(sockfd,PF_ON);
    EXPECT_EQ(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_nodelay(sockfd,PF_OFF);
    EXPECT_EQ(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_nodelay(sockfd,PF_INVALID);
    EXPECT_GT(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_nodelay(-1,PF_ON);
    EXPECT_GT(0,ret)<<errno;

    //pf_set_reuseaddr
    errno = 0;
    ret   = pf_set_reuseaddr(sockfd,PF_ON);
    EXPECT_EQ(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_reuseaddr(sockfd,PF_OFF);
    EXPECT_EQ(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_reuseaddr(sockfd,PF_INVALID);
    EXPECT_GT(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_reuseaddr(-1,PF_ON);
    EXPECT_GT(0,ret)<<errno;

    //pf_set_linger
    struct linger linger;
    linger.l_onoff  = 1;
    linger.l_linger = 1;
    errno           = 0;
    ret             = pf_set_linger(sockfd,&linger);
    EXPECT_EQ(0,ret)<<errno;

    linger.l_onoff = 0;
    errno          = 0;
    ret            = pf_set_linger(sockfd,&linger);
    EXPECT_EQ(0,ret)<<errno;

    //errno = 0;
    //ret   = pf_set_linger(sockfd,NULL);
    //EXPECT_GT(0,ret)<<errno;

    errno = 0;
    ret   = pf_set_linger(-1,&linger);
    EXPECT_GT(0,ret)<<errno;

    //pf_set_recvbuf
    errno = 0;
    size  = 512;
    ret   = pf_set_recvbuf(sockfd,size);
    EXPECT_EQ(0,ret)<<errno;

    errno = 0;
    size  = 0;
    ret   = pf_set_recvbuf(sockfd,size);
    EXPECT_EQ(0,ret)<<errno;

    //TODO size=-1 return 0?
    size  = -1;
    errno = 0;
    ret   = pf_set_recvbuf(sockfd,size);
    EXPECT_EQ(0,ret)<<errno;

    errno = 0;
    size  = 512;
    ret   = pf_set_recvbuf(-1,size);
    EXPECT_GT(0,ret)<<errno;

    //pf_set_sendbuf
    errno = 0;
    size  = 512;
    ret   = pf_set_sendbuf(sockfd,size);
    EXPECT_EQ(0,ret)<<errno;

    errno = 0;
    size  = 0;
    ret   = pf_set_sendbuf(sockfd,size);
    EXPECT_EQ(0,ret)<<errno;

    //TODO size=-1 return 0?
    errno = 0;
    size  = -1;
    ret   = pf_set_sendbuf(sockfd,size);
    EXPECT_EQ(0,ret)<<errno;

    errno = 0;
    size  = 512;
    ret   = pf_set_sendbuf(-1,size);
    EXPECT_GT(0,ret)<<errno;

    close(sockfd);
}

TEST_F(PfNetTest, pf_read_n_net_test)
{
    int ret;
    int sockfd;
    pf_family_e family;
    uint16_t backlog;
    int connfd;
    int32_t count;
    int yes;
    struct sockaddr_in client_addr;
    typedef struct sockaddr SA;
    socklen_t len     = sizeof(struct sockaddr_in);
    uint16_t port_lis = 10013;
    int32_t size      = 2*1024*1024;
    char *buf         = (char*)malloc(sizeof(char)*2*1024*1024);
    EXPECT_NE((char*)NULL, buf);
    memset(buf,1,size);
    //char buf[2*1024*1024];

    sockfd = socket(AF_INET,SOCK_STREAM,0);
    ret    = pf_set_reuseaddr(sockfd,PF_ON);
    EXPECT_EQ(0, ret)<<errno;
    family  = PF_INETV4;
    backlog = 5;
    errno   = 0;
    yes     = 1;
    EXPECT_EQ(0, setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)));  
    ret     = pf_listen(sockfd,listen_ip,port_lis,family,backlog);
    EXPECT_EQ(0, ret)<<errno;


    Option_t opt ; 
    opt.timeout    = -1;
    opt.block_type = PF_FD_BLOCK;
    opt.counts     = 6;
    opt.port       = port_lis;
    opt.send       = 1;
    //start a client thread to write data to server
    start_thread(client_func_write,(void*)&opt);

    //timeou = -1
    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_OFF);
        errno = 0;
        ret   = pf_read_n(connfd, PF_FD_BLOCK, buf, size, opt.timeout); //block type
        EXPECT_EQ(size,ret)<<errno;
        close(connfd);
    }

    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_ON);
        errno = 0;
        ret   = pf_read_n(connfd, PF_FD_NONBLOCK, buf, size, opt.timeout);//nonblock type
        EXPECT_EQ(size,ret)<<errno;
        close(connfd);
    }

    //timeout = 0,imediately
    opt.timeout = 0;
    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_OFF);
        errno = 0;
        ret = pf_read_n(connfd, PF_FD_BLOCK, buf, size, opt.timeout);//block type
        EXPECT_GE(size,ret)<<errno;
        close(connfd);
    }

    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_ON);
        errno = 0;
        ret = pf_read_n(connfd, PF_FD_NONBLOCK, buf, size, opt.timeout); //nonblock type
        EXPECT_GE(size,ret)<<errno;
        close(connfd);
    }

    //timeout = 2s
    opt.timeout = 2*1000;
    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_OFF);
        errno = 0;
        ret = pf_read_n(connfd, PF_FD_BLOCK, buf, size, opt.timeout); //block type
        EXPECT_EQ(size,ret)<<errno;
        close(connfd);
    }

    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_ON);
        errno = 0;
        ret = pf_read_n(connfd, PF_FD_NONBLOCK, buf, size, opt.timeout);//nonblock type
        EXPECT_EQ(size,ret)<<errno;
        close(connfd);
    }

    //2s timeout,no data to read
    usleep(1000);
    opt.timeout    = 2*1000;
    opt.block_type = PF_FD_BLOCK;
    opt.counts     = 2;
    opt.send       = 0;
    start_thread(client_func_write,(void*)&opt);

    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_OFF);
        errno = 0;
        ret = pf_read_n(connfd, PF_FD_BLOCK, buf, size, opt.timeout);
        EXPECT_EQ(-1,ret)<<errno;
        close(connfd);
    }

    usleep(1000);
    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_ON);
        errno = 0;
        ret = pf_read_n(connfd, PF_FD_NONBLOCK, buf, size, opt.timeout);
        EXPECT_EQ(-1,ret)<<errno;
        close(connfd);
    }

    //1ms timeout,no data to read
    usleep(1000);
    opt.timeout    = 1;
    opt.block_type = PF_FD_BLOCK;
    opt.counts     = 2;
    opt.send       = 0;
    start_thread(client_func_write,(void*)&opt);

    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_OFF);
        errno = 0;
        ret = pf_read_n(connfd, PF_FD_BLOCK, buf, size, opt.timeout);
        EXPECT_EQ(-1,ret)<<errno;
        close(connfd);
    }

    usleep(1000);
    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_ON);
        errno = 0;
        ret = pf_read_n(connfd, PF_FD_NONBLOCK, buf, size, opt.timeout);
        EXPECT_EQ(-1,ret)<<errno;
        close(connfd);
    }
    close(sockfd);
    free(buf);
}

TEST_F(PfNetTest, pf_write_n_net_test)
{
    int ret;
    int sockfd;
    int count;
    Option_t opt ; 
    pf_family_e family    = PF_INETV4;
    int32_t size          = 2*1024*1024;
    char *buf = (char*)malloc(sizeof(char)*2*1024*1024);
    EXPECT_NE((char*)NULL, buf);
    memset(buf,1,size);
    //char buf[2*1024*1024];

    opt.timeout    = -1;
    opt.block_type = PF_FD_BLOCK;
    opt.counts     = 6;
    opt.port       = 10011;
    opt.send       = 1;
    //start a server thread to read data
    start_thread(server_func_read,(void*)&opt);
    usleep(1000);

    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout);
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_OFF)<<ret;

        errno = 0;
        ret = pf_write_n(sockfd,PF_FD_BLOCK, buf, size, opt.timeout);
        EXPECT_EQ(size,ret)<<errno;
        close(sockfd);
    }
    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout);
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_ON)<<ret;

        errno = 0;
        ret = pf_write_n(sockfd,PF_FD_NONBLOCK, buf, size, opt.timeout);
        EXPECT_EQ(size,ret)<<errno;
        close(sockfd);
    }

    //
    opt.timeout = 0;
    count       = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout);
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_OFF)<<ret;

        errno = 0;
        ret = pf_write_n(sockfd,PF_FD_BLOCK, buf, size, opt.timeout);
        EXPECT_GE(size,ret)<<errno;
        close(sockfd);
    }
    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout);
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_ON)<<ret;

        errno = 0;
        ret = pf_write_n(sockfd,PF_FD_NONBLOCK, buf, size, opt.timeout);
        EXPECT_GE(size,ret)<<errno;
        close(sockfd);
    }
    //
    opt.timeout = 2*1000;
    count       = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout);
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_OFF)<<ret;

        errno = 0;
        ret = pf_write_n(sockfd,PF_FD_BLOCK, buf, size, opt.timeout);
        EXPECT_EQ(size,ret)<<errno;
        close(sockfd);
    }
    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout);
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_ON)<<ret;

        errno = 0;
        ret = pf_write_n(sockfd,PF_FD_NONBLOCK, buf, size, opt.timeout);
        EXPECT_EQ(size,ret)<<errno;
        close(sockfd);
    }

    usleep(1000);
    opt.timeout = 2*1000;
    opt.counts  = 2;
    opt.send    = 0;
    start_thread(server_func_read,(void*)&opt);
    usleep(1000);

    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout);
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_OFF)<<ret;

        errno = 0;
        ret = pf_write_n(sockfd,PF_FD_BLOCK, buf, size, opt.timeout);
        EXPECT_EQ(-1,ret)<<errno;
        close(sockfd);
    }
    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout);
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_ON)<<ret;

        errno = 0;
        ret = pf_write_n(sockfd,PF_FD_NONBLOCK, buf, size, opt.timeout);
        EXPECT_EQ(-1,ret)<<errno;
        close(sockfd);
    }
    free(buf);

}

TEST_F(PfNetTest, pf_readv_n_net_test)
{
    int ret;
    int sockfd;
    pf_family_e family;
    uint16_t backlog;
    int connfd;
    int32_t count;
    struct sockaddr_in client_addr;
    typedef struct sockaddr SA;
    socklen_t len = sizeof(struct sockaddr_in);
    int yes;
    struct iovec iov[2];
    char *buf1 = (char*)malloc(sizeof(char)*1024*1024);
    char *buf2 = (char*)malloc(sizeof(char)*1024*1024);
    EXPECT_NE((char*)NULL, buf1);
    EXPECT_NE((char*)NULL, buf2);
    memset(buf1,1,1024*1024);
    memset(buf2,1,1024*1024);
    iov[0].iov_base   = buf1;
    iov[0].iov_len    = 1024*1024;
    iov[1].iov_base   = buf2;
    iov[1].iov_len    = 1024*1024;
    int iovcnt        = 2;
    uint16_t port_lis = 10014;

    sockfd = socket(AF_INET,SOCK_STREAM,0);
    ret    = pf_set_reuseaddr(sockfd,PF_ON);
    EXPECT_EQ(0, ret)<<errno;

    family  = PF_INETV4;
    backlog = 5;
    errno   = 0;
    yes     = 1;
    EXPECT_EQ(0, setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)));  
    ret     = pf_listen(sockfd,listen_ip,port_lis,family,backlog);
    EXPECT_EQ(0, ret)<<errno;


    Option_t opt ; 
    opt.timeout    = -1;
    opt.block_type = PF_FD_BLOCK;
    opt.counts     = 6;
    opt.port       = port_lis;
    opt.send       = 1;
    start_thread(client_func_writev,(void*)&opt);

    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_OFF);
        errno = 0;
        ret = pf_readv_n(connfd, PF_FD_BLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(2*1024*1024,ret)<<errno;
        close(connfd);
    }

    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_ON);
        errno = 0;
        ret = pf_readv_n(connfd, PF_FD_NONBLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(2*1024*1024,ret)<<errno;
        close(connfd);
    }

    opt.timeout = 0;
    count       = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_OFF);
        errno = 0;
        ret = pf_readv_n(connfd, PF_FD_BLOCK, iov, iovcnt, opt.timeout);
        EXPECT_GE(2*1024*1024,ret)<<errno;
        close(connfd);
    }

    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_ON);
        errno = 0;
        ret = pf_readv_n(connfd, PF_FD_NONBLOCK, iov, iovcnt, opt.timeout);
        EXPECT_GE(2*1024*1024,ret)<<errno;
        close(connfd);
    }

    opt.timeout = 2*1000;
    count       = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_OFF);
        errno = 0;
        ret = pf_readv_n(connfd, PF_FD_BLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(2*1024*1024,ret)<<errno;
        close(connfd);
    }

    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_ON);
        errno = 0;
        ret = pf_readv_n(connfd, PF_FD_NONBLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(2*1024*1024,ret)<<errno;
        close(connfd);
    }

    //test timeout 2s,no data to read
    opt.timeout = 2*1000;
    opt.counts  = 2;
    opt.send    = 0;
    start_thread(client_func_writev,(void*)&opt);
    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_OFF);
        errno = 0;
        ret = pf_readv_n(connfd, PF_FD_BLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(-1,ret);
        EXPECT_EQ(PF_ETIMEDOUT,errno)<<errno;
        close(connfd);
    }
    usleep(1000);

    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_ON);
        errno = 0;
        ret = pf_readv_n(connfd, PF_FD_NONBLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(-1,ret)<<errno;
        close(connfd);
    }

    //test timeout 1ms,no data to read
    opt.timeout = 1;
    opt.counts  = 2;
    opt.send    = 0;
    start_thread(client_func_writev,(void*)&opt);

    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_OFF);
        errno = 0;
        ret = pf_readv_n(connfd, PF_FD_BLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(-1,ret)<<errno;
        close(connfd);
    }
    usleep(1000);

    count = 1;
    while(count--)
    {
        connfd = accept(sockfd,(SA*)&client_addr,&len); 
        pf_set_nonblock(connfd,PF_ON);
        errno = 0;
        ret = pf_readv_n(connfd, PF_FD_NONBLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(-1,ret)<<errno;
        close(connfd);
    }
    usleep(1000);

    close(sockfd);
    free(buf1);
    free(buf2);
}

TEST_F(PfNetTest, pf_writev_n_net_test)
{
    int ret;
    int sockfd;
    pf_family_e family = PF_INETV4;
    struct iovec iov[2];
    char *buf1 = (char*)malloc(sizeof(char)*1024*1024);
    char *buf2 = (char*)malloc(sizeof(char)*1024*1024);
    EXPECT_NE((char*)NULL, buf1);
    EXPECT_NE((char*)NULL, buf2);
    memset(buf1,1,1024*1024);
    memset(buf2,1,1024*1024);
    iov[0].iov_base = buf1;
    iov[0].iov_len  = 1024*1024;
    iov[1].iov_base = buf2;
    iov[1].iov_len  = 1024*1024;
    int iovcnt      = 2;
    int count;

    Option_t opt ; 

    //timeout is -1,Infinite timeout
    opt.timeout    = -1;
    opt.block_type = PF_FD_BLOCK;
    opt.counts     = 6;
    opt.port       = 10012;
    opt.send       = 1;

    start_thread(server_func_readv,(void*)&opt);
    usleep(1000);

    //writev block

    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout); 
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_OFF);
        EXPECT_EQ(0,ret);

        errno = 0;
        ret = pf_writev_n(sockfd,PF_FD_BLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(2*1024*1024,ret)<<"errno:"<<errno;
        close(sockfd);
    }

    //writev nonblock
    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout); 
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_ON);
        EXPECT_EQ(0,ret);

        errno = 0;
        ret = pf_writev_n(sockfd,PF_FD_NONBLOCK, iov, iovcnt, opt.timeout); 
        EXPECT_EQ(2*1024*1024,ret)<<"errno:"<<errno;
        close(sockfd);
    }

    //timeout is 0,return imediately
    opt.timeout    = 0;
    count          = 1;
    //writev block
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout); 
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_OFF)<<ret;

        errno = 0;
        ret = pf_writev_n(sockfd,PF_FD_BLOCK, iov, iovcnt, opt.timeout);
        EXPECT_GE(2*1024*1024,ret)<<errno;
        close(sockfd);
    }

    //writev nonblock
    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout);
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_ON)<<ret;

        errno = 0;
        ret = pf_writev_n(sockfd,PF_FD_NONBLOCK, iov, iovcnt, opt.timeout);
        EXPECT_GE(2*1024*1024,ret)<<errno;
        close(sockfd);
    }

    //timeout is 2s
    opt.timeout=2*1000;
    //writev block
    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout); 
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_OFF)<<ret;

        errno = 0;
        ret = pf_writev_n(sockfd,PF_FD_BLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(2*1024*1024,ret)<<errno;
        close(sockfd);
    }

    //writev nonblock
    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout);
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_ON)<<ret;

        errno = 0;
        ret = pf_writev_n(sockfd,PF_FD_NONBLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(2*1024*1024,ret)<<errno;
        close(sockfd);
    }
    usleep(1000);

    opt.timeout = 2*1000;
    opt.counts  = 2;
    opt.send    = 0;
    start_thread(server_func_readv,(void*)&opt);
    usleep(1000);

    //writev block
    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout); 
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_OFF)<<ret;

        errno = 0;
        ret = pf_writev_n(sockfd,PF_FD_BLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(-1,ret)<<errno;
        close(sockfd);
    }

    //writev nonblock
    count = 1;
    while(count--)
    {
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        errno = 0;
        ret = pf_connect(sockfd,connect_ip,opt.port,family,opt.timeout);
        EXPECT_EQ(0,ret);
        ret=pf_set_nonblock(sockfd,PF_ON)<<ret;

        errno = 0;
        ret = pf_writev_n(sockfd,PF_FD_NONBLOCK, iov, iovcnt, opt.timeout);
        EXPECT_EQ(-1,ret)<<errno;
        close(sockfd);
    }
    free(buf1);
    free(buf2);
}
